package com.project.utils;

import com.project.vo.DbMessageVO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

/**
 * JWT工具类
 */
@Slf4j
@Configuration
public class JwtUtil {

    // 过期时间
    private static long JWT_TTL;

    @Value("${spring.redis.cache.time}")
    public void setJwtTTL(long jwtTTL) {
        JwtUtil.JWT_TTL = jwtTTL;
    }

    //设置秘钥明文
    public static final String JWT_KEY = "eJhbGciOiJIUzI1NiJ9eyJpc3MiOiJjY2ZAbGlqaWFxaWFuZyIsInVzZXJUeXBlIjoiMSIsImV4cCI6MTY5ODUwMTY0NiwidXNlcklkIjoiMSIsImlhdCI6MTY5ODUwMTY0Nn0NDtXr0RVRhfn7tLvUjEI3sfMMe6cBOLbFSIQBV3cik";

    public static String getUUID(){
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
    
    /**
     * 生成jtw
     * @param map token中要存放的数据
     */
    public static String createJWT(HashMap<String, Object> map) {
        return createJWT(map, JWT_TTL);
    }

    /**
     * 生成jtw
     * @param map token中要存放的数据
     */
    public static String createJWT(HashMap<String, Object> map, long ttl) {
        if (ttl < 0)
            ttl = JWT_TTL;
        JwtBuilder builder = getJwtBuilder(map, ttl, getUUID());// 设置过期时间
        return builder.compact();
    }

    /**
     * 生成jtw
     * @param map token中要存放的数据（
     */
    public static String createRefreshJWT(HashMap<String, Object> map) {
        JwtBuilder builder = getJwtBuilder(map, JWT_TTL * 2, getUUID());// 设置过期时间
        return builder.compact();
    }

    /**
     * 创建token
     */
    public static String createJWT(String id, HashMap<String, Object> map, Long ttlMillis) {
        JwtBuilder builder = getJwtBuilder(map, ttlMillis, id);// 设置过期时间
        return builder.compact();
    }

    private static JwtBuilder getJwtBuilder(HashMap<String, Object> map, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();

        long nowMillis = System.currentTimeMillis();

        Date now = new Date(nowMillis);
        if(ttlMillis == null){
            ttlMillis = JwtUtil.JWT_TTL;
        }


        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .setId(uuid)
                .setClaims(map)
                .setIssuer("ccf@lijiaqiang")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
                .setExpiration(expDate); // 设置过期时间
    }

    /**
     * 生成加密后的秘钥 secretKey
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }
    
    /**
     * 解析 token
     */
    public static Claims parseJWT(String token) {
        SecretKey secretKey = generalKey();

        Claims claims;
        try {
            claims = Jwts.parser()  //得到DefaultJwtParser
                    .setSigningKey(secretKey)         //设置签名的秘钥
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.error("无效的token!");
            claims = null;
        }
        return claims;
    }


    /**
     *  通过 jwt 获取用户id (学号/工号)
     */
    public static String getUserIdByAuthentication(String authentication) {
        try {
            Claims claims = parseJWT(authentication);

            return claims.get("userId").toString();
        } catch (Exception e) {
            return null;
        }

    }

    /**
     *  通过 jwt 获取用户id (学号/工号)
     */
    public static DbMessageVO parseDbMessageVO(String token) {
        try {
            Claims claims = parseJWT(token);

            String userId = claims.get("userId").toString();
            String url = claims.get("url").toString();
            String userName = claims.get("userName").toString();
            String password = claims.get("password").toString();
            String dbName = claims.get("dbName").toString();
            return DbMessageVO.builder()
                    .userId(Long.parseLong(userId))
                    .url(url)
                    .userName(userName)
                    .password(password)
                    .dbName(dbName)
                    .build();

        } catch (Exception e) {
            return null;
        }

    }

    /**
     *  通过 jwt 获取用户类型(权限)
     */
    public static String getAuthorityByToken(String token) {
        try {
            Claims claims = parseJWT(token);

            return claims.get("roleType").toString();
        } catch (Exception e) {
            return null;
        }

    }

    /**
     *  通过 jwt 获取用户id (学号/工号)
     */
    public static String getUserEmailByToken(String token) {
        try {
            Claims claims = parseJWT(token);

            return claims.get("email").toString();
        } catch (Exception e) {
            return null;
        }

    }

}